package cn.runagain.demo.wechatminiappdemo.controller;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.runagain.demo.wechatminiappdemo.aes.AesCodec;
import cn.runagain.demo.wechatminiappdemo.entity.User;
import cn.runagain.demo.wechatminiappdemo.entity.UserWechatEntry;
import cn.runagain.demo.wechatminiappdemo.repository.UserRepository;
import cn.runagain.demo.wechatminiappdemo.repository.UserWechatEntryRepository;
import cn.runagain.demo.wechatminiappdemo.utils.WechatDataDecrypt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidParameterSpecException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * created by
 *
 * @author tuxianchao
 * @date 2018/6/11 下午4:37
 */
@Controller
@RequestMapping("/wechat/user")
public class WxUserController {
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private UserWechatEntryRepository userWechatEntryRepository;

    private Logger logger = LoggerFactory.getLogger(WxUserController.class);
    @Value("${wechat.AppId}")
    private String appId;
    @Value("${wechat.AppSecret}")
    private String appSecret;

    /**
     * wechat miniApp login
     *
     * @param code 微信小程序登录code
     * @return
     */
    @RequestMapping("/login")
    @ResponseBody
    public Object login(@RequestParam("code") String code,
                        @RequestParam("rawData") String rawData) throws Exception {
        logger.info("[login] [login]");
        Map<String, String> resultMap = new HashMap<String, String>();
        StringBuffer wechatUrl = new StringBuffer();
        //微信登录url
        wechatUrl.append("https://api.weixin.qq.com/sns/jscode2session")
                .append("?appid=" + appId)
                .append("&secret=" + appSecret)
                .append("&js_code=" + code)
                .append("&grant_type=authorization_code");
        logger.info("[wechatUrl:{}]", wechatUrl);
        //请求微信服务器登录
        RestTemplate restTemplate = new RestTemplate();
        String wechatLoginResult = restTemplate.getForObject(wechatUrl.toString(), String.class);
        logger.info("[wechatLoginResult:{}]", wechatLoginResult);

        JSONObject jsonResult = JSONUtil.parseObj(wechatLoginResult);
        //session_key && openid && unionid
        String sessionKey = (String) jsonResult.get("session_key");
        String openId = (String) jsonResult.get("openid");
        String unionid = (String) jsonResult.get("unionid");
        if (StrUtil.isEmpty(sessionKey) || StrUtil.isEmpty(openId) || StrUtil.isEmpty(sessionKey)) {
            //登录失败
            resultMap.put("message", "failed");
        } else {
            resultMap.put("message", "success");
            //绑定应用内部账号
            UserWechatEntry userWechatEntry = userWechatEntryRepository.findByOpenid(openId);
            //创建用户
            JSONObject jsonObject = JSONUtil.parseObj(rawData);
            if (userWechatEntry == null) {
                /**
                 * {"nickName":"🍌叫我图图就可以了","gender":1,"language":"zh_CN","city":"Chengdu","province":"Sichuan","country":"China","avatarUrl":"https://wx.qlogo.cn/mmopen/vi_32/iaadC5T6yx7YRGGHymJXxIm3oqibq4bic4mP1gSu2ibL2yUtesnbhhTQBOCLuGPBRQTy1JvaCM7cFLvywe4kztJibug/132"}
                 */
                //emoji表情临时过滤数据库需要处理
                User user = new User();
                user.setNickName((String) jsonObject.get("nickName"));
                user.setUserHeadPic((String) jsonObject.get("avatarUrl"));
                User save = userRepository.save(user);
                userWechatEntryRepository.save(new UserWechatEntry(save.getUserId(), openId, sessionKey));

                logger.info("[创建用户:{}] [openid:{}]", user, openId);
            } else {
                Optional<User> userOptional = userRepository.findById(userWechatEntry.getUserId());

                User user = userOptional.get();
                //更新有头像
                user.setUserHeadPic((String) jsonObject.get("avatarUrl"));
                userRepository.save(user);
                //更新session_key
                userWechatEntry.setSessionKey(sessionKey);
                userWechatEntryRepository.save(userWechatEntry);
                logger.info("[user登录，修改头像：{}]", user);
            }

        }
        logger.info("[session_key:{}][openid:{}]", sessionKey, openId);

//        resultMap.put("session_key", sessionKey);
//        resultMap.put("openid", openId);
        if (!StrUtil.isEmpty(sessionKey)) {
//            resultMap.put("unionid", unionid);
        }
        logger.info("[return:{}]", JSONUtil.toJsonStr(resultMap));

        //生成3rd_session
//        resultMap.put("token", AesCodec.encrypt(openId + "_" + sessionKey, AesCodec.KEY));

        return resultMap;
    }

//    /**
//     * @param encryptedData
//     * @param signature
//     * @param iv
//     * @param rawData
//     * @param userInfo
//     * @return
//     */
//    @RequestMapping(value = "/info", method = RequestMethod.POST)
//    @ResponseBody
//    public Object info(@RequestBody String encryptedData,
//                       @RequestBody String signature,
//                       @RequestBody String iv,
//                       @RequestBody String rawData,
//                       @RequestBody String userInfo) {
//        logger.info("[encryptedData:{}]", encryptedData);
//        logger.info("[signature:{}]", signature);
//        logger.info("[iv:{}]", iv);
//        logger.info("[rawData:{}]", rawData);
//        logger.info("[userInfo:{}]", userInfo);
//
//        return null;
//    }

    /**
     * @param jsonArgs
     * @return
     */
    @RequestMapping(value = "/uploadstedata", method = RequestMethod.GET)
    @ResponseBody
    public Object info(String encryptedData, String errMsg, String iv) {

        logger.info("[encryptedData:{}]", encryptedData);
        logger.info("[errMsg:{}]", errMsg);
        logger.info("[iv:{}]", iv);

        JSONObject decrypt = WechatDataDecrypt.decrypt("", encryptedData, iv);
        logger.info("[data:{}]", decrypt);
        //解密数据


        return "1";
    }
}